﻿
using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace Bettzueche.DampfrossContinuum
{
    class EntfernungTiling
    {


        /// <summary>{ 0-1, 2, 3, 4, 5, 6-7, 8-11, 12-19, 20-35, >35 }. Array hält untere Intervallgrenzen.</summary>
        static readonly int[] Entfernungen = { 0, 2, 3, 4, 5, 6, 8, 12, 20, 36, Int32.MaxValue };


        public static int TileCount {
            get { return 10; }
        }

        public static int TilingCount {
            get { return 1; }
        }

        /// <summary>
        /// Gets the feature number the specified value has.
        /// </summary>
        /// <param name="hexDistance">The (positiv or zero!) value.</param>
        /// <returns>Intervall-/Merkmalsnummer der Entfernung
        /// </returns>
        public static int GetFeatureNumber(int hexDistance) {
            if (hexDistance < 0)
                hexDistance = -hexDistance;
            return FeaturNumberRekursiv(0, Entfernungen.Length - 1, hexDistance);
        }

        static int FeaturNumberRekursiv(int lower, int upper, int hexDistance) {
            if (lower+1 == upper)
                return lower;
            int mid = (upper + lower) / 2;
            if (hexDistance >= Entfernungen[mid]) {
                lower = mid;
            }
            if (hexDistance < Entfernungen[mid]) {
                upper = mid;
            }
            return FeaturNumberRekursiv(lower, upper, hexDistance);
        }

        /// <summary>
        /// Gets the medians of the specified partition numbers, that is the midpoint of the sub-interval (feature-range).
        /// </summary>
        /// <param name="features">The feature's indices.</param>
        /// <returns>Dictionary of feature range midpoints with feature index as key.</returns>
        public static Dictionary<int, double> GetMedians(int[] features) {
            Dictionary<int, double> medians = new Dictionary<int, double>();
            for (int i = 0; i < features.Length; i++) {
                int fNum = features[i];
                if (fNum < 0)
                    medians[fNum] = Double.NegativeInfinity;
                else if (fNum >= Entfernungen.Length-1) // letztes Element (= Unendlich) auch ausschließen
                    medians[fNum] = Double.PositiveInfinity;
                else
                    medians[fNum] = (Entfernungen[fNum+1] + Entfernungen[fNum]) / 2.0;
            }
            return medians;
        }

        [Conditional("DEBUG")]
        internal static void Test() {
            int f = 0;
            f = EntfernungTiling.GetFeatureNumber(15); // 7
            f = EntfernungTiling.GetFeatureNumber(1);  // 0
            f = EntfernungTiling.GetFeatureNumber(0);  // 0
            f = EntfernungTiling.GetFeatureNumber(40); // 9
            f = EntfernungTiling.GetFeatureNumber(-15);// 7
            f = EntfernungTiling.GetFeatureNumber(2);  // 1
            f = EntfernungTiling.GetFeatureNumber(3);  // 2
            var dic = EntfernungTiling.GetMedians(new int[] { f });
            int entf = (int)dic[f];
            Console.ReadKey();
        }
    }
}
